1322.
Произведение матриц
В лесу графини Мордвиновой. Петергоф. 1891. С годами у художника
развилось обостренное цветовое видение. Теперь он видит и может передать кистью
изменчивость цветов в зависимости от освещения и от рефлексов соседних
предметов. Живописец выписывает мягкие переходы зеленых, желтоватых и сероватых
оттенков стволов елей, хвои и мха. Но тонкие колористические изменения не
самоцель для художника: ими он стремится донести до зрителя реальную жизнь
природы. Картина вызывает у зрителя впечатление, что он находится внутри
лесного пространства, дает прочувствовать окружающую атмосферу сосновой чащобы.
Даны три квадратные матрицы A, B, C, каждая из которых имеет
размер n ´ n. Необходимо проверить равенство: A ´ B = C.
Вход. Каждый тест начинается значением n (n £ 500). Далее следуют три матрицы
A, B, C, каждая из которых представляется n
строками, содержащих в точности n
чисел. Элементы матриц А и В по модулю не превышают 1000. Последний тест
содержит n = 0 и не обрабатывается. Например,
в первом тесте следует проверить равенство
Выход. Для каждого теста в отдельной строке вывести “YES” или
“NO” в зависимости от того, имеет ли место равенство A ´ B = C или нет.
Пример
входа |
Пример
выхода |
2 1 2 3 4 1 3 2 3 5 9 11 21 2 1 2 3 4 1 3 2 3 5 9 10 21 0 |
YES NO |
теория вероятности
Тесты
были подобраны так, что простое умножение матриц с временной оценкой O(n3) дает Time Limit.
Задачу следует решать вероятностным методом.
Сгенерируем
вектор r длины n из 0 и 1. Вычислим вектора ABr
= A(Br) и Cr за O(n2).
Если они равны, то с вероятностью 50% можно сказать, что A ´ B = C. Проведем такое
тестирование, например, 10 раз. Тогда с вероятностью 1 – 1/210
получим правильный ответ.
ABr вычисляется так (умножение матриц и векторов ассоциативно):
сначала умножаем матрицу B на вектор r
за O(n2), получаем вектор. Потом множим
матрицу А на этот вектор опять за время O(n2).
Объявим рабочие массивы.
#define MAX 501
int a[MAX][MAX], b[MAX][MAX], c[MAX][MAX], r[MAX], r1[MAX], r2[MAX];
Читаем входные данные
для каждого теста. Последний тест содержит n
= 0 и не обрабатывается.
while (scanf("%d", &n), n)
{
for (i = 0; i < n; i++)
for (j = 0; j < n; j++) scanf("%d", &a[i][j]);
for (i = 0; i < n; i++)
for (j = 0; j < n; j++) scanf("%d", &b[i][j]);
for (i = 0; i < n; i++) for (j = 0; j < n; j++)
scanf("%d", &c[i][j]);
Для каждого теста проверку равенства ABr = Cr производим 10 раз.
for (cnt = 0; cnt < 10; cnt++)
{
Заполняем линейный массив r нулями и единицами
произвольным образом.
for (flag = i = 0; i < n; i++) r[i] = rand()
% 2;
Выполняем умножение r1 = Br.
for (i = 0; i < n; i++)
for (r1[i] = k = 0; k < n; k++) r1[i] +=
b[i][k] * r[k];
Выполняем умножение r2 = Ar1
= ABr.
for (i = 0; i < n; i++)
for (r2[i] = k = 0; k < n; k++) r2[i] +=
a[i][k] * r1[k];
Выполняем умножение r1 = Cr.
for (i = 0; i < n; i++)
for (r1[i] = k = 0; k < n; k++) r1[i] +=
c[i][k] * r[k];
Сравниваем массивы r2 и r1. То есть проверяем
равенство ABr = Cr. Если ABr ≠ Cr, то устанавливаем flag = 1.
for (i = 0; i < n; i++)
if (r1[i] != r2[i])
{
flag = 1; break;
}
if (flag) break;
}
Для текущего теста выводим ответ.
if (flag) printf("NO\n"); else printf("YES\n");
}